package com.ouwen.smartpay.utils;

import com.fm.common.order.PayServiceOrderBase;
import com.fm.common.order.ServiceOrderBase;
import com.fm.common.result.ServiceResultBase;
import com.fm.core.utils.enums.ResultStatus;
import com.ouwen.smartpay.domain.ServiceOrderResultWarpper;
import com.ouwen.smartpay.openapi.order.ServiceOrder;
import com.ouwen.smartpay.openapi.result.ServiceResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * @author <a href="http://youngitman.tech">青年IT男</a>
 * @version v1.0.0
 * @className ServiceInvokeHelp
 * @description
 * @JunitTest: {@link  }
 * @date 2020-05-06 11:17
 **/
public class InvokerHelper {

    static Logger logger = LoggerFactory.getLogger(InvokerHelper.class);

    public static <T extends ServiceResultBase> T invoke(ServiceOrderBase serviceOrderBase, Function<ServiceOrder, ServiceResult> function) {

        try {

            return (T) InvokerHelper.doInvoke(serviceOrderBase, (_serviceName, _serviceOrderBase) -> conversionToServiceOrder(_serviceName, _serviceOrderBase), function);

        } catch (Exception e) {

            logger.error("服务异常", e);

            ServiceResultBase result = new ServiceResultBase();

            result.setStatus(ResultStatus.failure);

            result.setCode(ResultStatus.failure.code());

            result.setDetail("调用服务失败");

            return (T) result;
        }
    }

    /***
     *
     * 服务调用
     *
     * @author liyong
     * @date 12:59 PM 2020/5/6
     * @param serviceOrderBase
     * @param buildServiceOrderFunction
     * @param invokeFunction
     * @exception
     * @return ServiceResultBase
     **/
    public static ServiceResultBase doInvoke(ServiceOrderBase serviceOrderBase,
                                             BiFunction<String, ServiceOrderBase, ServiceOrder> buildServiceOrderFunction,
                                             Function<ServiceOrder, ServiceResult> invokeFunction) throws Exception {

        Optional<String> serviceNameOptional = ServiceOrderResultMapUtils.findServiceNameByOrderClass(serviceOrderBase.getClass());

        if (serviceNameOptional.isPresent()) {

            String serviceName = serviceNameOptional.get();

            //转换为OpenApi的ServiceOrder
            ServiceOrder serviceOrder = buildServiceOrderFunction.apply(serviceName, serviceOrderBase);

            //调用openapi
            ServiceResult serviceResult = invokeFunction.apply(serviceOrder);

            //转换为调用方Result
            return conversionToServiceResult(serviceResult, serviceName);

        }

        throw new IllegalAccessException(String.format("服务Order【%s】转换Result关系配置异常", serviceOrderBase.getClass().getSimpleName()));

    }

    /***
     *
     * 转换调用方请求Order为OpenApi的ServiceOrder
     *
     * @author liyong
     * @date 11:07 AM 2020/5/6
     * @param payServiceOrder
     * @exception
     * @return ServiceOrder
     **/
    public static ServiceOrder conversionToServiceOrder(String serviceName, ServiceOrderBase payServiceOrder) {

        ServiceOrder serviceOrder = new ServiceOrder();

        serviceOrder.setGid(payServiceOrder.getGid());

        serviceOrder.setService(serviceName);

        serviceOrder.setGroup(payServiceOrder.getGroup());

        serviceOrder.setRequestNo(payServiceOrder.getRequestNo());

        if (PayServiceOrderBase.class.isAssignableFrom(ServiceOrderBase.class)) {

            PayServiceOrderBase payServiceOrderBase = (PayServiceOrderBase) payServiceOrder;

            serviceOrder.setMessageType(payServiceOrderBase.getMessageType());

            serviceOrder.setNotifyUrl(payServiceOrderBase.getNotifyUrl());
        }

        serviceOrder.setVersion(payServiceOrder.getVersion());

        serviceOrder.setParameters(payServiceOrder.getParameters());

        serviceOrder.setTimestamp(payServiceOrder.getTimestamp());

        serviceOrder.setPartnerId(payServiceOrder.getPartnerId());

        serviceOrder.setSubPartnerId(payServiceOrder.getSubPartnerId());

        serviceOrder.setDatas(payServiceOrder.getDatas());

        return serviceOrder;
    }

    /***
     *
     * 转换Openapi结果为调用方Reuslt
     *
     * @author liyong
     * @date 11:04 AM 2020/5/6
     * @param serviceResult
     * @exception
     * @return ServiceResultBase
     **/
    private static ServiceResultBase conversionToServiceResult(ServiceResult serviceResult, String serviceName) throws Exception {

        ServiceOrderResultWarpper warpper = ServiceOrderResultMapUtils.findByServiceName(serviceName);

        if (warpper == null) {

            throw new IllegalArgumentException(String.format("服务【%s】没有注册Order->Result映射关系", serviceName));

        }

        Class<?> resultClass = warpper.getServiceResultClass();

        ServiceResultBase result;

        result = (ServiceResultBase) resultClass.newInstance();

        result.setDatas(serviceResult.getDatas());

        result.setPartnerId(serviceResult.getPartnerId());

        result.setSubPartnerId(serviceResult.getSubPartnerId());

        result.setRequestNo(serviceResult.getRequestNo());

        result.setTimestamp(serviceResult.getTimestamp());

        result.setCode(serviceResult.getCode());

        result.setGid(serviceResult.getGid());

        result.setStatus(serviceResult.getStatus());

        result.setParameters(serviceResult.getParameters());

        return result;

    }
}
